#pragma once

#include <iostream>
#include <string>
#include <functional>
#include <cstring>
#include <cerrno>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "err.hpp"
#include "Task.hpp"
#include "ThreadPool_V4.hpp"
#include "log.hpp"

namespace ns_server
{
    const uint16_t default_port = 8888;
    const int backlog = 32;
    using func_t = std::function<std::string(std::string)>;

    class TcpServer;

    class ThreadDate
    {
    public:
        ThreadDate(int sock, std::string clientIp, uint16_t clientPort, TcpServer *ts)
            : _sock(sock),
              _clientIp(clientIp),
              _clientPort(clientPort),
              _ts(ts)
        {
        }

    public:
        int _sock;
        std::string _clientIp;
        uint16_t _clientPort;
        TcpServer *_ts;
    };

    class TcpServer
    {
    public:
        TcpServer(func_t func, uint16_t port = default_port) : _port(port), _func(func)
        {
        }

        void InitServer()
        {
            // 1.创建套接字
            _listensock = socket(AF_INET, SOCK_STREAM, 0);
            if (_listensock < 0)
            {
                logMessage(Fatal, "create listensock error,%s,errno: ", strerror(errno), errno);
                exit(SOCKET_ERR);
            }

            logMessage(Info, "create listensock success: %d", _listensock);

            // 2.绑定套接字
            struct sockaddr_in local;
            local.sin_family = AF_INET;
            local.sin_port = htons(_port);
            local.sin_addr.s_addr = INADDR_ANY;

            if (bind(_listensock, (struct sockaddr *)&local, sizeof(local)) < 0)
            {
                logMessage(Fatal, "bind error,%s,errno: %d", strerror(errno), errno);
                exit(BIND_ERR);
            }

            // 3.监听
            if (listen(_listensock, backlog) < 0)
            {
                logMessage(Fatal, "listen error,%s,errno: %d", strerror(errno), errno);
                exit(LISTEN_ERR);
            }
            logMessage(Info, "listen sock success");
        }

        void Start()
        {
            signal(SIGCHLD, SIG_IGN); // 忽略子进程的信号
            while (true)
            {
                struct sockaddr_in client;
                memset(&client, 0, sizeof(client));
                socklen_t len = sizeof(client);
                int sock = accept(_listensock, (struct sockaddr *)&client, &len);
                if (sock < 0)
                {
                    logMessage(Warning, "accept client error,%s,errno: %d", strerror(errno), errno);
                    continue;
                }
                logMessage(Info, "connect client success,get %d from %d", sock, _listensock);

                std::string clientIp = inet_ntoa(client.sin_addr);
                uint16_t clientPort = ntohs(client.sin_port);

                // 线程池
                Task t(sock, clientIp, clientPort, std::bind(&TcpServer::service, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
                ThreadPool<Task>::getInstance()->pushTask(t);
            }
        }

        // 处理服务函数
        void service(int sock, std::string clientIp, uint16_t clientPort)
        {
            std::string name = "[" + clientIp + ":" + std::to_string(clientPort) + "]";
            char buffer[1024];
            while (true)
            {
                int n = read(sock, buffer, sizeof(buffer) - 1);
                if (n > 0)
                {
                    buffer[n] = '\0';
                    logMessage(Info, "%s# %s", name.c_str(), buffer);
                    std::string responce = _func(buffer);
                    int m = write(sock, responce.c_str(), responce.size());
                }
                else if (n == 0)
                {
                    // 写端关闭
                    logMessage(Info, "client%s quit,me to", name.c_str());
                    close(sock);
                    break;
                }
                else
                {
                    // 读数据异常
                    logMessage(Error, "read error,%s,errno: %d", strerror(errno), errno);
                    break;
                }
            }
        }
        ~TcpServer()
        {
        }

    private:
        int _listensock; // 监听套接字
        uint16_t _port;  // 端口号
        func_t _func;    // 处理函数
    };
}